import 'dart:async';
import 'dart:io';

import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
import 'package:im_flutter_sdk/im_flutter_sdk.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import 'package:qunaimedical/im/common_widgets.dart';
import 'package:qunaimedical/components/show_large_image.dart';
import 'package:qunaimedical/im/chat/chat_input_bar.dart';
import 'package:qunaimedical/im/chat_voice_player.dart';
import 'package:qunaimedical/utils/dialog_util.dart';
import 'package:qunaimedical/utils/log_util.dart';
import 'package:qunaimedical/utils/toast_util.dart';
import 'package:record_amr/record_amr.dart';

import 'chat_face_view.dart';
import 'chat_items/chat_item.dart';
import 'chat_more_view.dart';

class ChatPage extends StatefulWidget {
  static const String routeName = '/chat';

  ChatPage(
    EMConversation conversation,
  ) : conv = conversation;

  final EMConversation conv;

  @override
  State<StatefulWidget> createState() => _ChatPageState();
}

class _ChatPageState extends State<ChatPage> implements ChatInputBarListener {
  final String _tag = '_ChatPageState';

  List<ChatMoreViewItem>? items;

  final _scrollController = ScrollController();

  /// 时间显示间隔为1分钟
  final int _timeInterval = 60 * 1000;

  ChatInputBar? _inputBar;

  // 用来决定是否显示时间
  int _adjacentTime = 0;
  ChatInputBarType _inputBarType = ChatInputBarType.normal;
  ChatVoicePlayer _voicePlayer = ChatVoicePlayer();
  ChatMoreView? _moreView;
  TextEditingController _inputBarEditingController = TextEditingController();
  late StreamSubscription<bool> keyboardSubscription;
  bool _keyboardVisible = false;
  bool _showTip = true;

  /// 消息List
  List<EMMessage> _msgList = [];

  @override
  void initState() {
    super.initState();
    // 监听键盘弹起收回
    var keyboardVisibilityController = KeyboardVisibilityController();
    keyboardSubscription =
        keyboardVisibilityController.onChange.listen((bool visible) {
      print('Keyboard visibility update. Is visible: $visible');
      _keyboardVisible = visible;
      _setStateAndMoreToListViewEnd();
    });
    _inputBarEditingController.addListener(() {});
    items = [
      ChatMoreViewItem(
          'images/chat_input_more_photo.png', '相册', _moreViewPhotoBtnOnTap),
      ChatMoreViewItem(
          'images/chat_input_more_video.png', '视频', _moreCameraBtnOnTap),
      ChatMoreViewItem(
          'images/chat_input_more_file.png', '文件', _moreFileBtnOnTap),
    ];

    _moreView = ChatMoreView(items);
    // 添加环信回调监听
    _addChatListener();
    // 设置所有消息已读
    widget.conv.markAllMessagesAsRead();

    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.minScrollExtent) {
        _loadMessages(moveBottom: false);
      }
    });
    if (widget.conv.type == EMConversationType.ChatRoom) {
      EMClient.getInstance.chatRoomManager
          .joinChatRoom(widget.conv.id)
          .then((value) => _loadMessages());
    } else {
      _loadMessages();
    }
  }

  void dispose() {
    // 移除键盘监听
    keyboardSubscription.cancel();
    // 移除环信回调监听
    EMClient.getInstance.chatManager.removeEventHandler(widget.conv.id);
    _scrollController.dispose();
    _inputBarEditingController.dispose();
    if (widget.conv.type == EMConversationType.ChatRoom) {
      EMClient.getInstance.chatRoomManager.leaveChatRoom(widget.conv.id);
    }
    super.dispose();
  }

  @override
  Widget build(context) {
    _inputBar = ChatInputBar(
      listener: this,
      barType: _inputBarType,
      textController: _inputBarEditingController,
    );

    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: Text(widget.conv.ext?["name"] ?? ""),
      ),
      body: GestureDetector(
        // 点击背景隐藏键盘
        onTap: () {
          if (_keyboardVisible) {
            _inputBarType = ChatInputBarType.normal;
            SystemChannels.textInput.invokeMethod('TextInput.hide');
            setState(() {});
          }
        },
        child: SafeArea(
          child: Column(
            children: <Widget>[
              Offstage(
                offstage: !_showTip,
                child: Stack(
                  children: [
                    Container(
                      child: Text(
                        "不可发送超过10秒或文件过大的视频文件。\n病例文件打不开时，请点击“我的会诊--管理”，点击“病例文件管理--预览”，预览文件内容。",
                        style: Theme.of(context).textTheme.bodySmall,
                      ),
                      padding: EdgeInsets.all(16),
                      decoration: BoxDecoration(color: Colors.grey[200]),
                    ),
                    Positioned(
                      child: IconButton(
                        icon: Icon(
                          Icons.close,
                          color: Colors.grey,
                        ),
                        onPressed: () {
                          setState(() {
                            _showTip = false;
                          });
                        },
                      ),
                      right: 0,
                      top: 0,
                    )
                  ],
                ),
              ),
              // 消息内容
              Flexible(
                child: Container(
                  // padding: EdgeInsets.only(bottom: 20),
                  color: Color.fromRGBO(242, 242, 242, 1.0),
                  child: Builder(builder: (context) {
                    return CustomScrollView(
                      controller: _scrollController,
                      slivers: [
                        SliverList(
                          delegate: SliverChildBuilderDelegate(
                            (_, int index) {
                              return ChangeNotifierProvider<
                                  ChatVoicePlayer>.value(
                                value: _voicePlayer,
                                child: _chatItemFromMessage(
                                    _msgList[index], index),
                              );
                            },
                            childCount: _msgList.length,
                          ),
                        ),
                      ],
                    );
                  }),
                ),
              ),
              // 间隔线
              Divider(height: 1.0),
              // 输入框
              Container(
                // 限制输入框高度
                constraints: BoxConstraints(
                  maxHeight: (90),
                  minHeight: (44),
                ),
                decoration: new BoxDecoration(
                  color: Theme.of(context).cardColor,
                ),
                child: _inputBar,
              ),
              _bottomWidget(),
            ],
          ),
        ),
      ),
    );
  }

  /// 返回消息item
  _chatItemFromMessage(EMMessage msg, int index) {
    _makeMessageAsRead(msg);
    bool needShowTime = false;
    if (_adjacentTime == 0 ||
        (msg.serverTime - _adjacentTime).abs() > _timeInterval ||
        index == 0) {
      needShowTime = true;
    }

    _adjacentTime = msg.serverTime;

    List<Widget> widgetsList = [];

    if (needShowTime) {
      widgetsList.add(
        Container(
          margin: EdgeInsets.only(top: (10)),
          child: Text(
            timeStrByMs(msg.serverTime, showTime: true),
            style: TextStyle(color: Colors.grey),
          ),
        ),
      );
    }

    widgetsList.add(
      Container(
        constraints: BoxConstraints(
          minWidth: double.infinity,
        ),
        child: ChatItem(
          msg,
          onTap: (message) => _messageBubbleOnTap(message),
          errorBtnOnTap: (message) => _resendMessage(message),
          longPress: (message) => _messageOnLongPress(message),
        ),
        margin: EdgeInsets.only(
          top: (20),
          bottom: (20),
        ),
      ),
    );
    return Column(
      children: widgetsList,
    );
  }

  /// 发送消息已读回执
  _makeMessageAsRead(EMMessage msg) async {
    if (msg.chatType == EMConversationType.Chat &&
        msg.direction == MessageDirection.RECEIVE) {
      if (msg.hasReadAck == false) {
        try {
          await EMClient.getInstance.chatManager.sendMessageReadAck(msg);
        } on EMError {}
      }
      if (msg.hasRead == false) {
        try {
          await widget.conv.markMessageAsRead(msg.msgId);
        } on EMError {}
      }
    }
  }

  /// 输入框下部分View
  _bottomWidget() {
    if (_inputBarType == ChatInputBarType.more) {
      return _moreView;
    } else if (_inputBarType == ChatInputBarType.emoji) {
      return ChatFaceView(
        _inputBarEditingController.text.length > 0,
        onFaceTap: (expression) {
          _inputBarEditingController.text =
              _inputBarEditingController.text + '[${expression.name}]';
          setState(() {});
        },
        onDeleteTap: () {
          if (_inputBarEditingController.text.length > 0) {
            _inputBarEditingController.text = _inputBarEditingController.text
                .substring(0, _inputBarEditingController.text.length - 1);
          }
        },
        onSendTap: () => _sendTextMessage(_inputBarEditingController.text),
      );
    } else {
      return Container();
    }
  }

  /// 下拉加载更多消息
  _loadMessages({int count = 20, bool moveBottom = true}) async {
    try {
      List<EMMessage> msgs = await widget.conv.loadMessages(
          startMsgId: _msgList.length > 0 ? _msgList.first.msgId : '',
          loadCount: count);
      _msgList.insertAll(0, msgs);
    } on EMError {
    } finally {
      if (moveBottom) {
        _setStateAndMoreToListViewEnd();
      } else {
        setState(() {});
      }
    }
  }

  /// 刷新View并滑动到最底部
  _setStateAndMoreToListViewEnd() {
    setState(() {});
    Future.delayed(Duration(milliseconds: 100), () {
      _scrollController.jumpTo(_scrollController.position.maxScrollExtent);
    });
  }

  /// 点击bubble
  _messageBubbleOnTap(EMMessage msg) async {
    switch (msg.body.type) {
      case MessageType.TXT:
        break;
      case MessageType.IMAGE:
        {
          EMImageMessageBody body = msg.body as EMImageMessageBody;
          Image img;
          if (body.fileStatus != DownloadStatus.SUCCESS) {
            img = Image.network(
              body.remotePath!,
              fit: BoxFit.cover,
            );
          } else {
            img = Image.file(
              File(body.localPath),
              fit: BoxFit.cover,
            );
          }
          Navigator.of(context).push(
            MaterialPageRoute(
              builder: (_) {
                return ShowLargeImage(img);
              },
            ),
          );
        }
        break;
      case MessageType.VOICE:
        {
          if (_voicePlayer.currentMsgId == msg.msgId) {
            _voicePlayer.stopPlay();
          } else {
            _voicePlayer.playVoice(msg);
          }
        }
        break;
      case MessageType.VIDEO:
        break;
      case MessageType.LOCATION:
        break;
      case MessageType.FILE:
        break;
      case MessageType.CMD:
        break;
      case MessageType.CUSTOM:
        break;
      default:
        break;
    }
  }

  /// 消息长按
  _messageOnLongPress(EMMessage msg) {
    print('长按 msg id ---- ${msg.msgId}');
  }

  /// 发送文字消息
  _sendTextMessage(String txt) {
    if (txt.length == 0) return;
    EMMessage msg =
        EMMessage.createTxtSendMessage(targetId: widget.conv.id, content: txt);
    _sendMessage(msg);
    _inputBarEditingController.text = '';
  }

  /// 发送图片消息
  _sendImageMessage(String imagePath, [String fileName = '']) {
    Image.file(
      File(imagePath),
      fit: BoxFit.contain,
    )
        .image
        .resolve(ImageConfiguration())
        .addListener(ImageStreamListener((ImageInfo info, bool _) {
      EMMessage msg = EMMessage.createImageSendMessage(
        targetId: widget.conv.id,
        filePath: imagePath,
        displayName: fileName,
      );
      EMImageMessageBody body = msg.body as EMImageMessageBody;
      body.height = info.image.height.toDouble();
      body.width = info.image.width.toDouble();
      msg.body = body;
      _sendMessage(msg);
    }));
  }

  /// 发送视频消息
  _sendVideoMessage(String videoPath, [String fileName = '']) {
    EMMessage msg = EMMessage.createVideoSendMessage(
      targetId: widget.conv.id,
      filePath: videoPath,
      displayName: fileName,
    );
    EMVideoMessageBody body = msg.body as EMVideoMessageBody;
    body.height = 100;
    body.width = 100;
    msg.body = body;
    _sendMessage(msg);
  }

  /// 发送文件消息
  _sendFileMessage(String filePath, String fileName) {
    EMMessage msg = EMMessage.createFileSendMessage(
      targetId: widget.conv.id,
      filePath: filePath,
      displayName: fileName,
    );
    EMFileMessageBody body = msg.body as EMFileMessageBody;
    msg.body = body;
    _sendMessage(msg);
  }

  /// 发消息方法
  _sendMessage(EMMessage msg) async {
    _chatType() {
      ChatType type = ChatType.Chat;
      switch (widget.conv.type) {
        case EMConversationType.Chat:
          type = ChatType.Chat;
          break;
        case EMConversationType.ChatRoom:
          type = ChatType.ChatRoom;
          break;
        case EMConversationType.GroupChat:
          type = ChatType.GroupChat;
          break;
        default:
      }
      return type;
    }

    msg.chatType = _chatType();
    EMMessage message = await EMClient.getInstance.chatManager.sendMessage(msg);
    _msgList.add(message);
    _setStateAndMoreToListViewEnd();
  }

  /// 重发消息
  void _resendMessage(EMMessage msg) async {
    // _msgList.remove(msg);
    await EMClient.getInstance.chatManager.resendMessage(msg);
    // _msgList.add(msg);
    _setStateAndMoreToListViewEnd();
  }

  /// 相册按钮被点击
  _moreViewPhotoBtnOnTap() async {
    showDialog(
        context: context,
        builder: (c) {
          return SimpleDialog(
            children: [
              SimpleDialogOption(
                child: Padding(
                  padding: const EdgeInsets.symmetric(vertical: 8.0),
                  child: Text('从相册选取'),
                ),
                onPressed: () => _selectImage(ImageSource.gallery),
              ),
              SimpleDialogOption(
                child: Padding(
                  padding: const EdgeInsets.symmetric(vertical: 8.0),
                  child: Text('使用相机拍摄'),
                ),
                onPressed: () => _selectImage(ImageSource.camera),
              ),
            ],
          );
        });
  }

  void _selectImage(ImageSource source) async {
    Navigator.pop(context);
    PermissionStatus status = await Permission.camera.request();
    Log.d(_tag, "camera status:$status");
    if (source == ImageSource.gallery || status == PermissionStatus.granted) {
      XFile? pickedFile = await ImagePicker().pickImage(source: source);
      if (pickedFile != null) {
        _sendImageMessage(
          pickedFile.path,
        );
      }
    }
    if (source == ImageSource.camera &&
        status == PermissionStatus.permanentlyDenied) {
      DialogUtil.showAlertDialog(context, "您需要授予相机权限才可以进行拍照。", onPressed: () {
        Navigator.pop(context);
        openAppSettings();
      });
    }
  }

  /// 视频按钮被点击
  _moreCameraBtnOnTap() async {
    showDialog(
        context: context,
        builder: (c) {
          return SimpleDialog(
            children: [
              SimpleDialogOption(
                child: Padding(
                  padding: const EdgeInsets.symmetric(vertical: 8.0),
                  child: Text('从相册选取'),
                ),
                onPressed: () => _selectVideo(ImageSource.gallery),
              ),
              SimpleDialogOption(
                child: Padding(
                  padding: const EdgeInsets.symmetric(vertical: 8.0),
                  child: Text('使用相机拍摄'),
                ),
                onPressed: () => _selectVideo(ImageSource.camera),
              ),
            ],
          );
        });
  }

  _selectVideo(ImageSource source) async {
    Navigator.pop(context);
    PermissionStatus status = await Permission.camera.request();
    Log.d(_tag, "camera status:$status");
    if (source == ImageSource.gallery || status == PermissionStatus.granted) {
      XFile? pickedFile = await ImagePicker().pickVideo(source: source);
      if (pickedFile != null) {
        var size = File(pickedFile.path).lengthSync();
        print(size);
        if (size > 10 * 1024 * 1024) {
          ToastUtil.show('所选视频文件不能大于10MB');
        } else {
          _sendVideoMessage(pickedFile.path);
        }
      }
    }
    if (source == ImageSource.camera &&
        status == PermissionStatus.permanentlyDenied) {
      DialogUtil.showAlertDialog(context, "您需要授予相机权限才可以进行拍照。", onPressed: () {
        Navigator.pop(context);
        openAppSettings();
      });
    }
  }

  _moreFileBtnOnTap() async {
    PermissionStatus status = await Permission.storage.request();
    if (status == PermissionStatus.granted) {
      FilePickerResult? result = await FilePicker.platform.pickFiles(
        type: FileType.custom,
        allowedExtensions: ['xls', 'xlsx', 'pdf', 'doc', 'docx'],
      );
      if (result != null) {
        File file = File(result.files.single.path!);
        _sendFileMessage(
            file.path,
            file.path
                .substring(file.path.lastIndexOf("/") + 1, file.path.length));
      }
    }
    if (status == PermissionStatus.permanentlyDenied) {
      DialogUtil.showAlertDialog(context, "您需要授予文件读写权限。", onPressed: () {
        Navigator.pop(context);
        openAppSettings();
      });
    }
  }

  /// 大头针按钮被点击
  // _moreVoiceCallBtnOnTap() {
  //   if (widget.conv.type == EMConversationType.Chat) {
  //     EaseCallKit.startSingleCall(widget.conv.id);
  //   }
  // }
  //
  // _moreVideoCallBtnOnTap() {
  //   if (widget.conv.type == EMConversationType.Chat) {
  //     EaseCallKit.startSingleCall(widget.conv.id,
  //         callType: EaseCallType.SingeVideo);
  //   }
  // }

  @override
  void voiceBtnDragInside() {
    print('录音按钮内部');
  }

  @override
  void voiceBtnDragOutside() {
    print('录音按钮外部');
  }

  @override
  void voiceBtnTouchDown() async {
    if (await Permission.microphone.request().isGranted) {
      RecordAmr.startVoiceRecord((volume) {
        print('volume -- $volume');
      }).then((value) {
        if (value) {
          print('录制开始');
        } else {
          print('录制失败');
        }
      });
    } else {
      openAppSettings();
    }
  }

  @override
  void voiceBtnTouchUpInside() {
    RecordAmr.stopVoiceRecord((path, duration) {
      if (duration > 0) {
        EMMessage msg = EMMessage.createVoiceSendMessage(
          targetId: widget.conv.id,
          filePath: path,
          duration: duration,
        );
        _sendMessage(msg);
      } else {
        print('录制时间太短');
      }
    });
  }

  @override
  void voiceBtnTouchUpOutside() {
    print('录音按钮被外部抬起');
    _setStateAndMoreToListViewEnd();
  }

  @override
  void emojiBtnOnTap() {
    if (_inputBarType == ChatInputBarType.emoji) {
      _inputBarType = ChatInputBarType.input;
    } else {
      _inputBarType = ChatInputBarType.emoji;
    }
    _setStateAndMoreToListViewEnd();
  }

  @override
  void moreBtnOnTap() {
    if (_inputBarType == ChatInputBarType.more) {
      _inputBarType = ChatInputBarType.input;
    } else {
      _inputBarType = ChatInputBarType.more;
    }
    _setStateAndMoreToListViewEnd();
  }

  @override
  void textFieldOnTap() {
    _inputBarType = ChatInputBarType.input;
    _setStateAndMoreToListViewEnd();
  }

  @override
  void recordOrTextBtnOnTap({bool isRecord = false}) {
    if (_inputBarType == ChatInputBarType.normal) {
      _inputBarType = ChatInputBarType.input;
    } else {
      _inputBarType = ChatInputBarType.normal;
    }

    _setStateAndMoreToListViewEnd();
  }

  @override
  void sendBtnOnTap(String str) => _sendTextMessage(str);

  void _addChatListener() {
    EMClient.getInstance.chatManager.addEventHandler(
      widget.conv.id,
      EMChatEventHandler(
        onMessagesReceived: (messages) {
          for (var msg in messages) {
            if (msg.conversationId == widget.conv.id) {
              _msgList.add(msg);
            }
          }
          _setStateAndMoreToListViewEnd();
        },
      ),
    );
  }
}
